﻿using System;
using System.Collections.Generic;
using System.Linq;
using Nuwanda.TfsSpotlight.Data;
using Nuwanda.Common;
using Nuwanda.TfsSpotlight.Services.Interfaces;
using Nuwanda.TfsSpotlight.Shell.Services.Interfaces;
using StructureMap;
using Nuwanda.TfsSpotlight.TFS;

namespace Nuwanda.TfsSpotlight.Services
{
    [Author("Bartłomiej Legiędź")]
    [Pluggable("UserSettingsService")]
    public class UserSettingsService : IUserSettingsService
    {
        private const string ShellLayoutStateFileName = "ShellLayout.state";
        private const string QueryLayoutStateFileName = "QueryLayout.{0}.state";
        private const string ApplicationSettingsFileName = "Application.settings";
        private const string ProjectConfigurationFileName = "Project.{0}.{1}.config";

        private IIsolatedStorageService IsolatedStorageService { get; set; }
        private IVisualStudioServersRegister VisualStudioServersRegister { get; set; } 

        public UserSettingsService(IIsolatedStorageService isolatedStorageService,
                                   IVisualStudioServersRegister visualStudioServersRegister)
        {
            this.IsolatedStorageService = isolatedStorageService;
            this.VisualStudioServersRegister = visualStudioServersRegister;
        }

        public void SaveShellLayoutState(ShellLayoutState layoutState)
        {
            if (layoutState == null) return;

            var oldShellLayoutState = LoadShellLayoutState();
            if (oldShellLayoutState != null)
            {
                if (layoutState.WindowState != System.Windows.Forms.FormWindowState.Normal)
                {
                    layoutState.Location = oldShellLayoutState.Location;
                    layoutState.Size = oldShellLayoutState.Size;
                }

                if (layoutState.WindowState == System.Windows.Forms.FormWindowState.Minimized)
                    layoutState.WindowState = System.Windows.Forms.FormWindowState.Normal;

                if (!layoutState.ProjectPaneExpanded)
                {
                    layoutState.ProjectsPaneWith = oldShellLayoutState.ProjectsPaneWith;
                }

                if (!layoutState.HistoryPaneExpanded)
                {
                    layoutState.HistoryPaneWith = oldShellLayoutState.HistoryPaneWith;
                }
            }

            this.IsolatedStorageService.Save(layoutState, ShellLayoutStateFileName);
        }

        public ShellLayoutState LoadShellLayoutState()
        {
            return this.IsolatedStorageService.Load<ShellLayoutState>(ShellLayoutStateFileName);
        }

        public void SaveQueryLayoutState(QueryLayoutState layoutState, QueryDescriptor query)
        {
            if (layoutState == null) return;
            if (query == null) return;

            var oldQueryLayoutState = LoadQueryLayoutState(query);
            if (oldQueryLayoutState != null)
            {
                if (!layoutState.QueryResultExpanded)
                {
                    layoutState.QueryResultHeight = oldQueryLayoutState.QueryResultHeight;
                }
            }

            this.IsolatedStorageService.Save(layoutState, GetQueryLayoutStateFileName(query));
        }

        public QueryLayoutState LoadQueryLayoutState(QueryDescriptor query)
        {
            return this.IsolatedStorageService.Load<QueryLayoutState>(GetQueryLayoutStateFileName(query));
        }

        private static string GetQueryLayoutStateFileName(QueryDescriptor query)
        {
            return String.Format(QueryLayoutStateFileName, query.Guid);
        }

        public ApplicationSettings GetSettings()
        {
            var settings = this.IsolatedStorageService.Load<ApplicationSettings>(ApplicationSettingsFileName);

            if(settings == null)
                settings = GetDefaultSettings();

            settings.MarkOld();
            return settings;
        }

        private ApplicationSettings GetDefaultSettings()
        {
            var settings = new ApplicationSettings
                               {
                                   ServersSettings = new ServersSettings()
                               };

            var serversSettings = new ServersSettings();

            foreach (var server in this.DiscoverServers())
            {
                if (!serversSettings.Servers.Contains(server))
                    serversSettings.Servers.Add(server);
            }

            settings.ServersSettings = serversSettings;

            this.SaveSettings(settings);

            return settings;
        }

        public void SaveSettings(ApplicationSettings settings)
        {
            this.IsolatedStorageService.Save(settings, ApplicationSettingsFileName);
            settings.MarkOld();
        }

        public IList<ServerDescriptor> GetServers()
        {
            var settings = GetSettings();
            return settings.ServersSettings.Servers;
        }

        public List<ServerDescriptor> DiscoverServers()
        {
            var servers = this.VisualStudioServersRegister.GetServerNames();

            var serverDict = new Dictionary<string, ServerDescriptor>();

            foreach (var server in servers)
            {
                var url = new Uri(server);
                if (serverDict.ContainsKey(url.Host + url.Port)) continue;

                var serverDescriptor = new ServerDescriptor(server, server);
                serverDict.Add(url.Host + url.Port, serverDescriptor);
            }

            return serverDict.Values.ToList();
        }

        public void GetProjectConfiguration(ProjectDescriptor projectDescriptor)
        {
            if(projectDescriptor == null) return;

            var server = projectDescriptor.Server.GetUrlForFileName();

            projectDescriptor.Configuration = this.IsolatedStorageService.Load<ProjectConfiguration>(
                                                  String.Format(ProjectConfigurationFileName, server, projectDescriptor.Name))
                                                  ?? new ProjectConfiguration();

        }

        public void SaveProjectConfiguration(ProjectDescriptor projectDescriptor)
        {
            if (projectDescriptor == null) return;
            if (projectDescriptor.Configuration == null) return;

            var server = projectDescriptor.Server.GetUrlForFileName();
            this.IsolatedStorageService.Save(projectDescriptor.Configuration, String.Format(ProjectConfigurationFileName, server, projectDescriptor.Name));
        }
    }
}